package com.demo.springmvc.controller;

import com.demo.springmvc.exception.SelfException;
import com.demo.springmvc.pojo.Address;
import com.demo.springmvc.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author liangliang
 */
@Controller
@RequestMapping("springmvc")
@SessionAttributes(value = {"age"})
public class IndexController {

    private final ResourceBundleMessageSource messageSource;

    @Autowired
    public IndexController(ResourceBundleMessageSource messageSource) {this.messageSource = messageSource;}

    /**
     * HelloWord示例
     *
     * @return
     */
    @RequestMapping("helloword")
    public String hello() {
        return "helloword";
    }

    @RequestMapping(value = "requestParam", params = "action=get")
    public String requestParam(@RequestParam("action") String action, Model model,
                               @RequestHeader("Accept-Language") String encoding,
                               @CookieValue(value = "JSESSIONID", required = false) String sessionId) {
        model.addAttribute("param", action);
        model.addAttribute("encoding", encoding);
        model.addAttribute("sessionId", sessionId);
        return "requestParam";
    }

    @RequestMapping(value = "requestMethod", params = "action=post", method = RequestMethod.POST)
    public String requestMethod(@RequestParam("username") String username, @RequestParam("password") String password,
                                Model model) {
        if ("admin".equals(username) && "admin".equals(password)) {
            model.addAttribute("status", "成功");
        } else {
            model.addAttribute("status", "失败");
        }
        return "requestMethod";
    }

    /**
     * 占位符
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping(value = "pathVariable/{id}")
    public String pathVariable(@PathVariable("id") Integer id, Model model) {
        model.addAttribute("id", id);
        return "pathVariable";
    }

    /**
     * Rest风格URL
     */
    @RequestMapping(value = "rest")
    public String rest() {
        return "restUrl";
    }

    // get
    @RequestMapping(value = "restUrl/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String restUrlGet(@PathVariable("id") Integer id) {
        if (id != null) {
            return id + "数据获取成功";
        }
        return "数据为空";
    }

    // put (修改)
    @RequestMapping(value = "restUrl/{id}", method = RequestMethod.PUT, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String restUrlPut(@PathVariable("id") Integer id, @RequestParam("name") String name) {
        if (id != null) {
            return id + "数据修改成功，改后的值为：" + name;
        }
        return "数据修改失败";
    }

    // post (新增)
    @RequestMapping(value = "restUrl", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String restUrlPost(@RequestParam("name") String name) {
        if (name != null) {
            return "数据新增成功，id 为 1,name 为" + name;
        }
        return "数据新增失败";
    }

    // delete (删除)
    @RequestMapping(value = "restUrl/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String restUrlDelete(@PathVariable("id") Integer id) {

        if (id != null) {
            return id + "数据删除成功";
        }
        return "数据删除失败";
    }

    // antStyle Url
    @RequestMapping(value = "ant/?")
    public String antStyleUrl() {
        return "antStyle";
    }

    // POJO 风格
    @RequestMapping(value = "requestPojo", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String requestPojo(@Valid User user, BindingResult result) {
        if (result.getErrorCount() > 0) {
            System.out.println("出错了：");
            for (FieldError error : result.getFieldErrors()) {
                System.out.println(error.getField() + ":" + error.getDefaultMessage());
            }
        }
        if (user != null) {
            return user.toString();
        } else {
            return "null";
        }
    }

    @RequestMapping(value = "pojo")
    public String pojo() {
        return "pojo";
    }

    // Servlet API
    @RequestMapping(value = "servletApi")
    public void servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session)
        throws IOException {
        response.setCharacterEncoding("UTF-8");
        Writer out = response.getWriter();
        String name = request.getParameter("name");
        String title = "<!DOCTYPE html>\n"
            + "<html lang=\"en\">\n"
            + "<head>\n"
            + "    <meta charset=\"UTF-8\">\n"
            + "    <title>ServletAPI</title>\n"
            + "</head>\n"
            + "<body>\n"
            + "<h3>MVC 的 Handler 方法可以接受\n"
            + "ServletAPI类型的参数\n</h3>";
        String doc = "<ul><li>HttpServletRequest</li>\n"
            + "<li>HttpServletResponse</li>\n"
            + "<li>HttpSession</li>\n"
            + "<li>java.security.Principal</li>\n"
            + "<li>Locale</li>\n"
            + "<li>InputStream</li>\n"
            + "<li>OutputStream</li>\n"
            + "<li>Reader</li>\n"
            + "<li>Writer</li></ul>\n";

        String foot = "</body>\n"
            + "</html>";
        out.write(title + doc + "writer: " + name + "<br>session value: " + session.getAttribute("age") + foot);
    }

    // ModelAndView
    @RequestMapping(value = "modelAndView")
    public ModelAndView modelAndView(Model model) {
        ModelAndView mav = new ModelAndView();
        Map<String, Object> map = new HashMap<>();
        map.put("age", 18);
        mav.addObject("userName", "admin");
        mav.addAllObjects(map);
        mav.setViewName("modelAndView");
        return mav;
    }

    @ModelAttribute(value = "user")
    public User publicModel() {
        // 模拟从数据库查出的数据
        User user = new User();
        return user;
    }

    @RequestMapping(value = "modelAttribute", produces = "application/json;charset=utf-8")
    public String modelAttribute(@ModelAttribute("user") User user) {
        user.setAge(21);
        user.setAddress(new Address().setCity("beijing"));
        return "modelAttribute";
    }

    // jstl 国际化
    @RequestMapping(value = "jstl")
    public String jstl(Locale locale) {
        String username = messageSource.getMessage("i18n.username", null, locale);
        System.out.println("----------jstl国际化----" + locale.getLanguage() + "-----username：" + username);
        return "jstl";
    }

    // 自定义View
    @RequestMapping(value = "testView")
    public String testView() {
        return "myView";
    }

    // 重定向
    @RequestMapping(value = "redirect")
    public String testRedirect() {
        return "redirect:/";
    }

    // 数据绑定
    @RequestMapping(value = "databinding", method = RequestMethod.GET)
    public String testDataBinding() {
        return "databinding";
    }

    // 数据绑定
    @RequestMapping(value = "databinding", method = RequestMethod.POST)
    public String testDataBinding(@RequestParam("user") User user, Map<String, User> map) {
        map.put("userdata", user);
        return "databinding";
    }

    // 禁止某个字段回传
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.setDisallowedFields("username");
    }

    // 数据格式转换
    @RequestMapping("datatransfer")
    public String dataTransfer() {
        return "datatransfer";
    }

    // JSR 303 数据校验
    @RequestMapping("jsr303")
    public String jsr303() {
        return "jsr303";
    }

    // test jackson
    @RequestMapping("testJson")
    public String testJson() {
        return "testJson";
    }

    // test jackson
    @ResponseBody
    @RequestMapping(value = "testJackson", produces = "application/json;charset=utf-8")
    public User testJackson() {
        User user = new User();
        user.setAge(26);
        user.setUsername("codelight");
        user.setBirth(new Date());
        user.setSalary(99999L);
        user.setAddress(new Address().setCity("BJ"));
        return user;
    }

    @RequestMapping("testHttpMessageConverter")
    public String testHttpMessageConverter() {
        return "testHttpMessageConverter";
    }

    // RequestBody
    @RequestMapping(value = "httpMessageConverter", method = RequestMethod.POST,
        produces = "application/json;charset=utf-8")
    @ResponseBody
    public String testHttpMessageConverter(@RequestBody String body) {
        System.out.println(body);
        return "时间：" + new Date();
    }

    // Test ResponseEntity
    @RequestMapping("testResponseEntity")
    public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
        byte[] body = null;
        ServletContext servletContext = session.getServletContext();
        InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/static/file/file.txt");

        body = new byte[inputStream.available()];
        inputStream.read(body);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment;filename=my.txt");

        HttpStatus status = HttpStatus.OK;

        return new ResponseEntity<>(body, headers, status);
    }

    // 文件上传
    @RequestMapping("/fileUpload")
    public String fileUpload() {
        return "fileUpload";
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String upload(@RequestParam("des") String des, @RequestParam("files") MultipartFile[] files) {

        if (files != null && files.length > 0) {
            for (MultipartFile file : files) {
                System.out.println("fileName : " + file.getOriginalFilename());
            }
            System.out.println("desc: " + des);
            return "上传成功";
        }
        return "上传失败";
    }

    // 异常处理
    @RequestMapping("exception")
    @ResponseBody
    public String testException(@RequestParam("i") int i) {
        int result = 10 / i;
        System.out.println("result: " + result);
        return "success";
    }

    // ResponseStatusExceptionResolver
    @ResponseStatus(reason = "i不能等于0", value = HttpStatus.UNAUTHORIZED)
    @RequestMapping("testResponseStatusExceptionResolver")
    @ResponseBody
    public String testResponseStatusExceptionResolver(@RequestParam("i") int i) {
        if (i == 0) {
            throw new SelfException("i不能等于0");
        }
        System.out.println("Test ResponseStatusExceptionResolver");
        return "Success!";
    }

    //  异常处理 DefaultHandlerExceptionResolver 、SimpleMappingExceptionResolver
    @RequestMapping("testExceptionResolver")
    @ResponseBody
    public String testExceptionResolver(@RequestParam("i") int i) {
        String[] strs = new String[10];
        System.out.println("testExceptionResolver: " + strs[i]);
        return "Success!";
    }

}
